home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / lists / mint / l_1199 / 1717 < prev    next >
Encoding:
Internet Message Format  |  1994-08-27  |  37.5 KB

  1. Subject: Re: MiNTlib (I think I'm on pl43): Bug in sprintf().
  2. Date: Mon, 18 Jul 94 1:45:36 CDT
  3. From: Juergen Lock <nox@jelal.north.de>
  4. In-Reply-To: <9407130621.AA25156@hera.rbi.informatik.uni-frankfurt.de>; from "Kay Roemer" at Jul 13, 94 8:21 am
  5. Message-Id: <9407172345.AA00280@jelal.north.de>
  6.  
  7. Kay Roemer writes:
  8.  
  9. > > Probably normal, given that it's really polling at 60 times per second.
  10. > > So up to 30-some characters can arrive (at 19200) before polling, and then
  11. > > checkbttys is only called on a context switch, so yes, there could be a
  12. > > large number of characters waiting before select returns...
  13. > Well, I'm not taking of 30 characters, but about a screen full of them, ie
  14. > about 80x25=2000! When I use modm0dev which polls at 5 times per second
  15. > using a separate porcess I get much smaller hunks, about 500.
  16.  
  17.  thats on a 68000 right?  i guess you just found the `feature' that a
  18. RAW tty read is slower copying stuff out of the receiver buffer than
  19. data comes in at 19200 bps...  sounds unbelievable hmm? ;)  well, try this!
  20. (relative to 10h6)
  21.  
  22. 1. fix range checks, eliminate some dead code...
  23.  
  24. Index: bios.c
  25. @@ -80,24 +80,24 @@
  26.  
  27.  /* and then do BCOSTAT ourselves, the BIOS SCC ones are often broken */
  28.  #define BCOSTAT(dev) \
  29. -    (((unsigned)dev <= 4 && tosvers > 0x0102) ? \
  30. -       (int)callout1(xcostat[dev], dev) : \
  31. -       ((has_bconmap && (unsigned)((dev-SERDEV) <= btty_max)) ? \
  32. +    (((unsigned)dev <= 4) ? ((tosvers > 0x0102) ? \
  33. +       (int)callout1(xcostat[dev], dev) : Bcostat(dev)) : \
  34. +       ((has_bconmap && (unsigned)dev-SERDEV < btty_max) ? \
  35.          bcxstat(MAPTAB[dev-SERDEV].iorec+1) : Bcostat(dev)))
  36.  #define BCONOUT(dev, c) \
  37. -    (((unsigned)dev <= 4 && tosvers > 0x0102) ? \
  38. -       callout2(xconout[dev], dev, c) : \
  39. -       ((has_bconmap && (unsigned)((dev-SERDEV) <= btty_max)) ? \
  40. +    (((unsigned)dev <= 4) ? ((tosvers > 0x0102) ? \
  41. +       callout2(xconout[dev], dev, c) : Bconout(dev, c)) : \
  42. +       ((has_bconmap && (unsigned)dev-SERDEV < btty_max) ? \
  43.          callout2(MAPTAB[dev-SERDEV].bconout, dev, c) : Bconout(dev, c)))
  44.  #define BCONSTAT(dev) \
  45. -    (((unsigned)dev <= 4 && tosvers > 0x0102) ? \
  46. -       (int)callout1(xconstat[dev], dev) : \
  47. -       ((has_bconmap && (unsigned)((dev-SERDEV) <= btty_max)) ? \
  48. +    (((unsigned)dev <= 4) ? ((tosvers > 0x0102) ? \
  49. +       (int)callout1(xconstat[dev], dev) : Bconstat(dev)) : \
  50. +       ((has_bconmap && (unsigned)dev-SERDEV < btty_max) ? \
  51.          (int)callout1(MAPTAB[dev-SERDEV].bconstat, dev) : Bconstat(dev)))
  52.  #define BCONIN(dev) \
  53. -    (((unsigned)dev <= 4 && tosvers > 0x0102) ? \
  54. -       callout1(xconin[dev], dev) : \
  55. -       ((has_bconmap && (unsigned)((dev-SERDEV) <= btty_max)) ? \
  56. +    (((unsigned)dev <= 4) ? ((tosvers > 0x0102) ? \
  57. +       callout1(xconin[dev], dev) : Bconin(dev)) : \
  58. +       ((has_bconmap && (unsigned)dev-SERDEV < btty_max) ? \
  59.          callout1(MAPTAB[dev-SERDEV].bconin, dev) : Bconin(dev)))
  60.  #else
  61.  #define BCOSTAT(dev) \
  62. @@ -264,7 +264,14 @@
  63.          } else
  64.              h = dev-SERDEV;
  65.  
  66. -        if (h >= 0 && h < btty_max) {
  67. +        if ((unsigned)h < btty_max) {
  68. +            if (has_bconmap) {    /* help the compiler... :) */
  69. +                long *statc;
  70. +
  71. +                while (!callout1(*(statc=&MAPTAB[dev-SERDEV].bconstat), dev))
  72. +                    sleep(IO_Q, (long)&bttys[h]);
  73. +                return callout1(statc[1], dev);
  74. +            }
  75.              while (!BCONSTAT(dev))
  76.                  sleep(IO_Q, (long)&bttys[h]);
  77.          } else if (dev > 0) {
  78. Index: xbios.c
  79. @@ -145,10 +145,12 @@
  80.  uiorec(dev)
  81.      int dev;
  82.  {
  83. +    extern short btty_max;
  84. +
  85.      TRACE(("Iorec(%d)", dev));
  86.      if (dev == 0 && has_bconmap) {
  87.  /* get around another BIOS Bug:  in (at least) TOS 2.05 Iorec(0) is broken */
  88. -        if (curproc->bconmap >= 6)
  89. +        if ((unsigned)curproc->bconmap-6 < btty_max)
  90.              return (long)MAPTAB[curproc->bconmap-6].iorec;
  91.          mapin(curproc->bconmap);
  92.      }
  93. @@ -174,7 +176,7 @@
  94.  /* more bugs...  serial1 is three-wire, requesting hardware flowcontrol
  95.   * on it can confuse BIOS
  96.   */
  97. -        if ((flow & 2) && (unsigned)curproc->bconmap-6 <= btty_max &&
  98. +        if ((flow & 2) && (unsigned)curproc->bconmap-6 < btty_max &&
  99.              bttys[curproc->bconmap-6].rsel == &(ttmfp_tty.rsel))
  100.              flow &= ~2;
  101.  
  102. 2. serial lines, act 2
  103.  
  104. anyone remember my idea to add shortcuts for fast RAW tty IO in the DEVDRV
  105. struct?  well, looks like it works.  i can receive and display(!) nearly
  106. full 57600 bps now using my hack of howards little `tip' program...
  107. a while ago the same program had problems at 19200 and this 68000 runs
  108. at 16 MHz.  so its a factor >= 3 including output!
  109.  
  110. the iread() and iwrite() are mostly the ones i patched into taylor uucp 1.03
  111. so they have been tested for some time.  i hope 1.05 will no longer need
  112. any such hacks now... (imagine uucp-i on a ST :)
  113.  
  114. oh and memcpy is an extended quickmove really (quickmovb), and the XDEF'd
  115. _bcopy is just a hint for gcc that it doesn't need to load the libs
  116. bcopy too.
  117.  
  118. Index: file.h
  119. @@ -141,7 +141,15 @@
  120.      long ARGS_ON_STACK (*datime)    P_((FILEPTR *f, short *timeptr, int rwflag));
  121.      long ARGS_ON_STACK (*close)    P_((FILEPTR *f, int pid));
  122.      long ARGS_ON_STACK (*select)    P_((FILEPTR *f, long proc, int mode));
  123. -    void ARGS_ON_STACK (*unselect) P_((FILEPTR *f, long proc, int mode));
  124. +    void ARGS_ON_STACK (*unselect)    P_((FILEPTR *f, long proc, int mode));
  125. +/* extensions, check dev_descr.drvsize (size of DEVDRV struct) before calling:
  126. + * fast RAW tty byte io  */
  127. +    long ARGS_ON_STACK (*writeb)    P_((FILEPTR *f, const char *buf, long bytes));
  128. +    long ARGS_ON_STACK (*readb)    P_((FILEPTR *f, char *buf, long bytes));
  129. +/* what about: scatter/gather io for DMA devices...
  130. + *    long ARGS_ON_STACK (*writev)    P_((FILEPTR *f, const struct iovec *iov, long cnt));
  131. + *    long ARGS_ON_STACK (*readv)    P_((FILEPTR *f, const struct iovec *iov, long cnt));
  132. + */
  133.  } DEVDRV;
  134.  
  135.  typedef struct filesys {
  136. @@ -509,6 +517,8 @@
  137.      long        *rsel;        /* pointer to field in tty struct */
  138.      IOREC_T        *orec;        /* Same, for output... */
  139.      long        *wsel;
  140. +    long        ispeed, ospeed;
  141. +    long        *baudmap, maxbaud;
  142.  };
  143.  
  144.  /* Dcntl constants and types */
  145. @@ -521,7 +531,8 @@
  146.      short    dinfo;
  147.      short    flags;
  148.      struct tty *tty;
  149. -    long    reserved[4];
  150. +    long    drvsize;        /* size of DEVDRV struct */
  151. +    long    reserved[3];
  152.  };
  153.  
  154.  
  155. @@ -582,6 +593,7 @@
  156.      struct bios_file *next;
  157.      short    lockpid;        /* owner of the lock */
  158.      XATTR    xattr;            /* guess what... */
  159. +    long    drvsize;        /* size of DEVDRV struct */
  160.  };
  161.  
  162.  #endif /* _filesys_h */
  163. Index: mint.h
  164. @@ -139,6 +139,7 @@
  165.  #define strlwr    MS_lwr
  166.  #define strupr    MS_upr
  167.  #define sleep    M_sleep
  168. +#define memcpy    quickmovb
  169.  #endif
  170.  
  171.  #ifdef SHORT_NAMES
  172. @@ -170,6 +171,10 @@
  173.  #include "proto.h"
  174.  #include "sproto.h"
  175.  #endif
  176. +
  177. +#ifndef offsetof
  178. +#include <stddef.h>
  179. +#endif
  180.  
  181.  #ifndef NULL
  182.  #define NULL ((void *)0)
  183. Index: proto.h
  184. @@ -298,6 +298,7 @@
  185.  
  186.  /* tty.c */
  187.  long tty_read P_((FILEPTR *f, void *buf, long nbytes));
  188. +INLINE void tty_checkttou P_((FILEPTR *f, struct tty *tty));
  189.  long tty_write P_((FILEPTR *f, const void *buf, long nbytes));
  190.  long tty_ioctl P_((FILEPTR *f, int mode, void *arg));
  191.  long tty_getchar P_((FILEPTR *f, int mode));
  192. @@ -336,6 +337,8 @@
  193.  
  194.  /* biosfs.c */
  195.  void biosfs_init P_((void));
  196. +long iwrite    P_((int bdev, const char *buf, long bytes, int ndelay, struct bios_file *b));
  197. +long iread    P_((int bdev, char *buf, long bytes, int ndelay, struct bios_file *b));
  198.  void ARGS_ON_STACK mouse_handler P_((const char *buf));
  199.  long ARGS_ON_STACK nocreat P_((fcookie *dir, const char *name, unsigned mode, int attrib,
  200.           fcookie *fc));
  201. Index: bios.c
  202. @@ -694,7 +694,11 @@
  203.              return 0;
  204.          }
  205.          if (is_terminal(f)) {
  206. +            int oldflags = f->flags;
  207. +
  208.              s = bconbuf;
  209. +/* turn off NDELAY for this write... */
  210. +            f->flags &= ~O_NDELAY;
  211.              if (dev == 5) {
  212.                  while (bsiz-- > 0) {
  213.                  if (*s < ' ') {
  214. @@ -710,6 +714,24 @@
  215.  #if 1
  216.                  long *where, nbytes;
  217.  
  218. +#if 1
  219. +                extern FILESYS bios_filesys;
  220. +
  221. +                /* see if we can do fast RAW byte IO thru the device driver... */
  222. +                if ((f->fc.fs != &bios_filesys ||
  223. +                    (bsiz > 1 &&
  224. +                     ((struct bios_file *)f->fc.index)->drvsize >
  225. +                        offsetof (DEVDRV, writeb))) && *f->dev->writeb) {
  226. +                    struct tty *tty = (struct tty *)f->devinfo;
  227. +
  228. +                tty_checkttou (f, tty);
  229. +                if ((ret = (*f->dev->writeb)(f, s, bsiz)) != EUNDEV) {
  230. +                    f->flags = oldflags;
  231. +                    bconbdev = 0;
  232. +                    return ret;
  233. +                }
  234. +                }
  235. +#endif
  236.  /* the tty_putchar should set up terminal modes correctly */
  237.                  (void) tty_putchar(f, (long)*s++, RAW);
  238.                  where = lbconbuf;
  239. @@ -726,6 +748,7 @@
  240.  #endif
  241.              }
  242.              ret = -1;
  243. +            f->flags = oldflags;
  244.          } else {
  245.              ret = (*f->dev->write)(f, (char *)bconbuf, bsiz);
  246.          }
  247. @@ -739,6 +762,10 @@
  248.          dev = curproc->bconmap;
  249.          statdev = dev;
  250.      }
  251. +    if ((ret = iwrite (dev, bconbuf, bsiz, 0, 0)) != EUNDEV) {
  252. +        bconbdev = 0;
  253. +        return ret;
  254. +    }
  255.  /* compensate for a known BIOS bug; MIDI and IKBD are switched */
  256.      else if (dev == 3) {        /* MIDI */
  257.          statdev = 4;
  258. Index: biosfs.c
  259. @@ -35,6 +35,8 @@
  260.  static long    ARGS_ON_STACK bios_topen    P_((FILEPTR *f));
  261.  static long    ARGS_ON_STACK bios_twrite    P_((FILEPTR *f, const char *buf, long bytes));
  262.  static long    ARGS_ON_STACK bios_tread    P_((FILEPTR *f, char *buf, long bytes));
  263. +static long    ARGS_ON_STACK bios_writeb    P_((FILEPTR *f, const char *buf, long bytes));
  264. +static long    ARGS_ON_STACK bios_readb    P_((FILEPTR *f, char *buf, long bytes));
  265.  static long    ARGS_ON_STACK bios_nwrite    P_((FILEPTR *f, const char *buf, long bytes));
  266.  static long    ARGS_ON_STACK bios_nread    P_((FILEPTR *f, char *buf, long bytes));
  267.  static long    ARGS_ON_STACK bios_ioctl    P_((FILEPTR *f, int mode, void *buf));
  268. @@ -64,7 +66,8 @@
  269.  
  270.  DEVDRV bios_tdevice = {
  271.      bios_topen, bios_twrite, bios_tread, bios_tseek, bios_ioctl,
  272. -    null_datime, bios_close, bios_select, bios_unselect
  273. +    null_datime, bios_close, bios_select, bios_unselect,
  274. +    bios_writeb, bios_readb
  275.  };
  276.  
  277.  /* device driver for BIOS devices that are not terminals */
  278. @@ -146,9 +149,22 @@
  279.      {"", 0, 0, 0, 0, 0}
  280.  };
  281.  
  282. +#define xconstat ((long *)0x51eL)
  283. +#define xconin     ((long *)0x53eL)
  284. +#define xcostat ((long *)0x55eL)
  285. +#define xconout    ((long *)0x57eL)
  286. +
  287.  extern BCONMAP2_T *bconmap2;        /* bconmap struct */
  288.  #define MAPTAB (bconmap2->maptab)
  289.  
  290. +#define MAXBAUD 16
  291. +
  292. +/* keep these sorted in descending order */
  293. +static long baudmap[MAXBAUD] = {
  294. +19200L, 9600L, 4800L, 3600L, 2400L, 2000L, 1800L, 1200L,
  295. +600L, 300L, 200L, 150L, 134L, 110L, 75L, 50L
  296. +};
  297. +
  298.  /* set/reset bits in SCC w5 */
  299.  INLINE static void scc_set5 (control, setp, bits, iorec)
  300.  volatile char *control;
  301. @@ -183,6 +199,8 @@
  302.  struct bios_tty bttys[MAX_BTTY];
  303.  short    btty_max;
  304.  
  305. +extern int tosvers;    /* from main.c */
  306. +
  307.  /* Does the fcookie fc refer to the \dev\fd directory? */
  308.  #define IS_FD_DIR(fc) ((fc)->aux == S_IFDIR)
  309.  /* Does the fcookie fc refer to a file in the \dev\fd directory? */
  310. @@ -254,6 +272,10 @@
  311.      /* Save a pointer to the first serial port */
  312.          if (b->private == 6)
  313.              c = b;
  314. +        if (b->device->readb && b->tty != &con_tty)
  315. +    /* device has DEVDRV calls beyond unselect */
  316. +            b->drvsize = offsetof (DEVDRV, readb) + sizeof (long);
  317. +
  318.      /* if not a TT or Mega STE, adjust the MODEM1 device to be BIOS
  319.       * device 1
  320.       * and ignore the remaining devices, since they're not present
  321. @@ -281,12 +303,18 @@
  322.      }
  323.      /* Initialize bios_tty structures */
  324.      for (i=0;c && i<MAX_BTTY;c=c->next, i++) {
  325. +        unsigned r;
  326.          if (has_bconmap)
  327.              Bconmap(c->private);
  328.          bttys[i].irec = Iorec(0);
  329.          bttys[i].orec = bttys[i].irec+1;
  330.          bttys[i].rsel = &(c->tty->rsel);
  331.          bttys[i].wsel = &(c->tty->wsel);
  332. +        bttys[i].baudmap = baudmap;
  333. +        bttys[i].maxbaud = MAXBAUD;
  334. +        r = (int)rsconf(-2, -1, -1, -1, -1, -1);
  335. +        Rsconf(r, -1, -1, -1, -1, -1);
  336. +        bttys[i].ospeed = bttys[i].ispeed = r<MAXBAUD ? baudmap[r] : -1;
  337.      }
  338.      btty_max = i;
  339.  
  340. @@ -788,6 +816,7 @@
  341.   *       short  dinfo            info for the device driver
  342.   *       short  flags            flags for the file (e.g. O_TTY)
  343.   *       struct tty *tty        tty structure, if appropriate
  344. + *       long   drvsize;        size of driver struct
  345.   *
  346.   * Dcntl(0xde00, "U:\DEV\BAR", n): install a new BIOS terminal device, with
  347.   *     BIOS device number "n".
  348. @@ -835,6 +864,7 @@
  349.              b->private = d->dinfo;
  350.              b->flags = d->flags;
  351.              b->tty = d->tty;
  352. +            b->drvsize = d->drvsize;
  353.              set_xattr(&(b->xattr), S_IFCHR|DEFAULT_MODE, UNK_RDEV|devindex);
  354.              devindex = (devindex+1) & 0x00ff;
  355.              return (long)&kernelinfo;
  356. @@ -865,7 +895,11 @@
  357.                      return ENSMEM;
  358.                  b->tty = ttyptr;
  359.              }
  360. +            b->drvsize = 0;
  361.              b->device = &bios_tdevice;
  362. +            if (b->device->readb)
  363. +                /* device has DEVDRV calls beyond unselect */
  364. +                b->drvsize = offsetof (DEVDRV, readb) + sizeof (long);
  365.              b->private = arg;
  366.              b->flags = O_TTY;
  367.              *b->tty = default_tty;
  368. @@ -887,6 +921,7 @@
  369.               * who didn't recognize this change is still using it.
  370.               */
  371.              b->tty = 0;
  372. +            b->drvsize = 0;
  373.              b->device = &bios_ndevice;
  374.              b->private = arg;
  375.              b->flags = 0;
  376. @@ -1221,7 +1256,7 @@
  377.   * for cooked TTY output they will, which is the only sort that
  378.   * control characters affect anyways).
  379.   */
  380. -    if (bytes > 0 && (*r & 0x000000ffL) == '\n')
  381. +    if (bdev == 2 && bytes > 0 && (*r & 0x000000ffL) == '\n')
  382.          (void) checkkeys();
  383.  
  384.      if (f->flags & O_NDELAY) {
  385. @@ -1277,6 +1312,335 @@
  386.  }
  387.  
  388.  /*
  389. + * fast RAW byte IO for BIOS ttys
  390. + * without this a RAW tty read goes thru bios_tread for every single
  391. + * char, calling BIOS 3 times per byte at least...  a poor 8 MHz ST
  392. + * just can't move real 19200 bits per second that way, before a
  393. + * byte crawled thru all this the next has already arrived.
  394. + * if the device has xcon* calls and a `normal' iorec these functions
  395. + * access the buffers directly using as little CPU time as possible,
  396. + * for other devices they return EUNDEV (== do the slow thing then).
  397. + * yes it is a hack but better one hack here than hacks in every
  398. + * user process that wants good RAW IO performance...
  399. + */
  400. +
  401. +static long ARGS_ON_STACK 
  402. +bios_writeb(f, buf, bytes)
  403. +    FILEPTR *f; const char *buf; long bytes;
  404. +{
  405. +    int bdev = f->fc.aux;
  406. +    struct bios_file *b = (struct bios_file *)f->fc.index;
  407. +
  408. +    return iwrite (bdev, buf, bytes, (f->flags & O_NDELAY), b);
  409. +}
  410. +
  411. +/* FILEPTR-less entrypoint for bflush etc. */
  412. +
  413. +long
  414. +iwrite(bdev, buf, bytes, ndelay, b)
  415. +    int bdev; const char *buf; long bytes; int ndelay; struct bios_file *b;
  416. +{
  417. +    IOREC_T *ior = 0;
  418. +    long *cout = 0;    /* keep compiler happy */
  419. +    long *ospeed;
  420. +    const char *p = buf;
  421. +    int slept = 0;
  422. +
  423. +    if (has_bconmap) {
  424. +        if ((unsigned)bdev-6 < btty_max) {
  425. +            ior = MAPTAB[bdev-6].iorec + 1;
  426. +            cout = &MAPTAB[bdev-6].bconout;
  427. +            ospeed = &bttys[bdev-6].ospeed;
  428. +        }
  429. +    } else if (bdev == 1 && tosvers > 0x0102) {
  430. +        ior = bttys[0].orec;
  431. +        cout = &xconout[1];
  432. +        ospeed = &bttys[0].ospeed;
  433. +    }
  434. +
  435. +/* no iorec, fall back to the slow way... */
  436. +    if (!ior)
  437. +        return EUNDEV;
  438. +
  439. +    if (!buf) {
  440. +        /* flush send buffer...  should be safe to just set the
  441. +           tail pointer. */
  442. +        ior->tail = ior->head;
  443. +        return 0;
  444. +    }
  445. +
  446. +    if (!bytes)
  447. +        /* nothing to do... */
  448. +        return 0;
  449. +
  450. +    do {
  451. +        char ch;
  452. +        unsigned short tail, bsize, wrap, newtail;
  453. +        long free;
  454. +
  455. +        tail = ior->tail;
  456. +        bsize = ior->buflen;
  457. +        if ((free = (long)ior->head - tail - 1) < 0)
  458. +            free += bsize;
  459. +
  460. +        /* if buffer is full or we're blocking and can't write enuf */
  461. +        if ((unsigned long)free < 2 ||
  462. +            (!ndelay && free < bytes && free < bsize/2)) {
  463. +            long sleepchars;
  464. +            unsigned long isleep;
  465. +
  466. +            /* if the write should not block thats it. */
  467. +            if (ndelay)
  468. +                return p - buf;
  469. +
  470. +            /* else sleep the (minimum) time it takes until
  471. +               the buffer is either half-empty or has space
  472. +               enough for the write, wichever is smaller. */
  473. +            if ((sleepchars = bsize/2) > bytes)
  474. +                sleepchars = bytes;
  475. +            sleepchars -= free;
  476. +
  477. +            isleep = (unsigned long) ((sleepchars * 10000L) / *ospeed);
  478. +
  479. +            /* except that if we already slept and the buffer
  480. +               still was full we sleep for at least 20
  481. +               milliseconds. (driver must be waiting for
  482. +               some handshake signal and we don't want to
  483. +               hog the processor.) */
  484. +            if (slept && isleep < 20)
  485. +                isleep = 20;
  486. +
  487. +            if (isleep < 5)
  488. +                /* if it still would be less than 5
  489. +                   milliseconds then just give up this
  490. +                   timeslice */
  491. +                yield();
  492. +            else if (isleep < 20)
  493. +                nap (isleep);
  494. +            else {
  495. +                TIMEOUT *t;
  496. +
  497. +                if (isleep > 200)
  498. +                    isleep = 200;
  499. +                t = addtimeout((long)isleep, (void (*)(PROC *))wakeselect);
  500. +                if (t) {
  501. +                    sleep(SELECT_Q, (long)wakeselect);
  502. +                    canceltimeout(t);
  503. +                }
  504. +            }
  505. +
  506. +            /* loop and try again. */
  507. +            slept = (unsigned long)free < 2;
  508. +            continue;
  509. +        }
  510. +        slept = 0;
  511. +
  512. +        /* save the 1st char, we could need it later. */
  513. +        ch = *p;
  514. +        wrap = bsize - tail;
  515. +        if (--free > bytes)
  516. +            free = bytes;
  517. +        bytes -= free;
  518. +
  519. +        /* now copy to buffer.  if its just a few then do it here... */
  520. +        if (free < 5) {
  521. +            char *q = ior->bufaddr + tail;
  522. +
  523. +            while (free--) {
  524. +                if (!--wrap)
  525. +                    q -= bsize;
  526. +                *++q = *p++;
  527. +            }
  528. +            newtail = q - ior->bufaddr;
  529. +
  530. +        /* else use memcpy.  */
  531. +        } else {
  532. +            /* --wrap and tail+1 because tail is `inc before access' */
  533. +            if (--wrap < free) {
  534. +                memcpy (ior->bufaddr + tail + 1, p, wrap);
  535. +                memcpy (ior->bufaddr, p + wrap, free - wrap);
  536. +                newtail = free - wrap - 1;
  537. +            } else {
  538. +                memcpy (ior->bufaddr + tail + 1, p, free);
  539. +                newtail = tail + free;
  540. +            }
  541. +            p += free;
  542. +        }
  543. +
  544. +        /* the following has to be done with interrupts off to avoid
  545. +           race conditions. */
  546. +        {
  547. +            short sr = spl7();
  548. +
  549. +            /* if the buffer is empty there might be no
  550. +               interrupt that sends the next char, so we
  551. +               send it thru the xcon* vector. */
  552. +            if (ior->head == ior->tail) {
  553. +                (void) callout2(*cout, bdev, (unsigned char) ch);
  554. +
  555. +                /* if the buffer now is still empty set
  556. +                   the head pointer to skip the 1st char
  557. +                   (that we just sent). */
  558. +                if (ior->head == ior->tail) {
  559. +                    if (++tail >= bsize)
  560. +                        tail = 0;
  561. +                    ior->head = tail;
  562. +                }
  563. +            }
  564. +            ior->tail = newtail;
  565. +
  566. +            spl(sr);
  567. +            if (b) {
  568. +                b->xattr.mtime = b->xattr.atime = timestamp;
  569. +                b->xattr.mdate = b->xattr.adate = datestamp;
  570. +            }
  571. +        }
  572. +    /* if we're blocking loop until everything is written */
  573. +    } while (bytes && !ndelay);
  574. +
  575. +    return p - buf;
  576. +}
  577. +
  578. +/*
  579. + * fast RAW BIOS tty read
  580. + * this really works like a RAW tty read i.e. only blocks until _some_
  581. + * data is ready.
  582. + * TODO: implement termios VMIN, VTIME...
  583. + */
  584. +
  585. +static long ARGS_ON_STACK 
  586. +bios_readb(f, buf, bytes)
  587. +    FILEPTR *f; char *buf; long bytes;
  588. +{
  589. +    int bdev = f->fc.aux;
  590. +    struct bios_file *b = (struct bios_file *)f->fc.index;
  591. +
  592. +    return iread (bdev, buf, bytes, (f->flags & O_NDELAY), b);
  593. +}
  594. +
  595. +long
  596. +iread(bdev, buf, bytes, ndelay, b)
  597. +    int bdev; char *buf; long bytes; int ndelay; struct bios_file *b;
  598. +{
  599. +    IOREC_T *ior = 0;
  600. +    long *cin = 0;    /* keep compiler happy */
  601. +    long *cinstat;
  602. +    char *p;
  603. +    unsigned short head, bsize, wrap;
  604. +    long left;
  605. +
  606. +    if (bdev == 3 && tosvers > 0x0102) {
  607. +        /* midi */
  608. +        ior = (IOREC_T *) uiorec(2);
  609. +        cin = &xconin[3];
  610. +        cinstat = &xconstat[3];
  611. +    } else if (has_bconmap) {
  612. +        if ((unsigned)bdev-6 < btty_max) {
  613. +            ior = MAPTAB[bdev-6].iorec;
  614. +            cin = &MAPTAB[bdev-6].bconin;
  615. +            cinstat = &MAPTAB[bdev-6].bconstat;
  616. +        }
  617. +    } else if (bdev == 1 && tosvers > 0x0102) {
  618. +        ior = bttys[0].irec;
  619. +        cin = &xconin[1];
  620. +        cinstat = &xconstat[1];
  621. +    }
  622. +
  623. +/* no iorec, fall back to the slow way... */
  624. +    if (!ior)
  625. +        return EUNDEV;
  626. +
  627. +    if (buf && !bytes)
  628. +        /* nothing to do... */
  629. +        return 0;
  630. +
  631. +    /* if the read should block sleep until there is something to read */
  632. +    if (buf && !ndelay) {
  633. +        while (!(int)callout1(*cinstat, bdev)) {
  634. +            if (has_bconmap && (unsigned)bdev-6 < btty_max) {
  635. +                sleep(IO_Q, (long)&bttys[bdev-6]);
  636. +            } else if (bdev == 1) {
  637. +                sleep(IO_Q, (long)&bttys[0]);
  638. +            } else
  639. +                nap(60);
  640. +        }
  641. +    }
  642. +
  643. +    head = ior->head;
  644. +    if (!(left = ((unsigned long) ior->tail) - head)) {
  645. +        /* if the buffer is still empty we're finished... */
  646. +        return 0;
  647. +    }
  648. +
  649. +    /* now copy the data out of the buffer */
  650. +    bsize = ior->buflen;
  651. +    if (left < 0)
  652. +        left += bsize;
  653. +    wrap = bsize - head;
  654. +
  655. +    /* if we should flush input pretend we want to read it all */
  656. +    if (!buf && !bytes)
  657. +        bytes = left;
  658. +
  659. +    if (left > bytes)
  660. +        left = bytes;
  661. +
  662. +    /* if its just a few then do it here... */
  663. +    if (buf && left <= 5) {
  664. +        char *q = ior->bufaddr + head;
  665. +
  666. +        /* the --left in the while() makes us get one char less
  667. +           because we want to get the last one thru the driver
  668. +           so that it gets a chance to raise RTS or send XON... */
  669. +        p = buf;
  670. +        while (--left) {
  671. +            if (!--wrap)
  672. +                q -= bsize;
  673. +            *p++ = *++q;
  674. +        }
  675. +        ior->head = q - ior->bufaddr;
  676. +
  677. +    /* else memcpy is faster. */
  678. +    } else {
  679. +        /* --wrap and head+1 because head is `inc before access' */
  680. +        if (--wrap < --left) {
  681. +            if (buf) {
  682. +                memcpy (buf, ior->bufaddr + head + 1, wrap);
  683. +                memcpy (buf + wrap, ior->bufaddr, left - wrap);
  684. +            }
  685. +            ior->head = left - wrap - 1;
  686. +        } else {
  687. +            if (buf)
  688. +                memcpy (buf, ior->bufaddr + head + 1, left);
  689. +            ior->head = head + left;
  690. +        }
  691. +        /* p points to last char */
  692. +        p = buf + left;
  693. +    }
  694. +
  695. +    {
  696. +        short sr = spl7();
  697. +
  698. +        /* xconin[] are always blocking, and we don't want to
  699. +           hang at ipl7 even if something impossible like a
  700. +           `magically' empty buffer happens.  so check again. */
  701. +        if (ior->tail != ior->head)
  702. +            if (buf)
  703. +                *p++ = callout1(*cin, bdev);
  704. +            else
  705. +                (void) callout1(*cin, bdev);
  706. +        spl(sr);
  707. +        if (b) {
  708. +            b->xattr.atime = timestamp;
  709. +            b->xattr.adate = datestamp;
  710. +        }
  711. +    }
  712. +    if (!buf)
  713. +        return 0;
  714. +    return p - buf;
  715. +}
  716. +
  717. +/*
  718.   * read/write routines for BIOS devices that aren't terminals (like the
  719.   * printer & IKBD devices)
  720.   */
  721. @@ -1346,14 +1710,6 @@
  722.      return 0;
  723.  }
  724.  
  725. -#define MAXBAUD 16
  726. -
  727. -/* keep these sorted in descending order */
  728. -static long baudmap[MAXBAUD] = {
  729. -19200L, 9600L, 4800L, 3600L, 2400L, 2000L, 1800L, 1200L,
  730. -600L, 300L, 200L, 150L, 134L, 110L, 75L, 50L
  731. -};
  732. -
  733.  static long ARGS_ON_STACK 
  734.  bios_ioctl(f, mode, buf)
  735.      FILEPTR *f; int mode; void *buf;
  736. @@ -1395,16 +1751,23 @@
  737.              flushtype = (int) *r;
  738.          }
  739.          if (dev == 1 || dev >= 6) {
  740. +            b = (struct bios_file *)f->fc.index;
  741.              if (has_bconmap && dev >= 6)
  742.                  ior = MAPTAB[dev-6].iorec;
  743.              else
  744.                  ior = (IOREC_T *) uiorec(0);
  745. -            if (flushtype & 1) {
  746. +    /* just resetting iorec pointers here can hang a flow controlled port,
  747. +     * iread can do better...
  748. +     */
  749. +            if ((flushtype & 1) &&
  750. +                iread (dev, (char *) NULL, 0, 1, b) == EUNDEV) {
  751.                  sr = spl7();
  752.                  ior->head = ior->tail = 0;
  753.                  spl(sr);
  754.              }
  755. -            if (flushtype & 2) {
  756. +    /* sender should be ok but iwrite also sets the dev's ctime */
  757. +            if ((flushtype & 2) &&
  758. +                iwrite (dev, (char *) NULL, 0, 1, b) == EUNDEV) {
  759.                  ior++; /* output record */
  760.                  sr = spl7();
  761.                  ior->head = ior->tail = 0;
  762. Index: quickmov.spp
  763. @@ -6,14 +6,49 @@
  764.  ; quickly copy "nbytes" bytes from src to dst. Assumes that both
  765.  ; src and dst are word aligned.
  766.  ;
  767. +; quickmovb(char *dst, char *src, long nbytes):
  768. +; like memcpy, does unaligned too...  does not check for overlap (memmove).
  769. +;
  770.      TEXT
  771.  
  772.      XDEF    _quickmove
  773. +    XDEF    _quickmovb
  774.  
  775. +;%ifdef OWN_LIB
  776. +    XDEF    _bcopy
  777. +    XDEF    __bcopy
  778. +
  779. +_bcopy:
  780. +__bcopy:
  781. +    move.l    8(sp),a0        ; get dst
  782. +    move.l    4(sp),a1        ; get src
  783. +    bra.s    _quickmovb1
  784. +;%endif
  785. +
  786. +_quickmovb:
  787. +    move.l    4(sp),a0        ; get dst
  788. +    move.l    8(sp),a1        ; get src
  789. +_quickmovb1:
  790. +    move.w    a0,d0
  791. +    move.w    a1,d1
  792. +    eor.w    d1,d0            ; bit 0 == unaligned
  793. +    lsr.w    #1,d0            ; ...now in x flag
  794. +    move.l    12(sp),d0        ; get nbytes
  795. +    beq.s    Ldone
  796. +    roxr.w    #1,d1            ; bit 0 == both odd, msb == unaligned
  797. +    bmi.s    bytecopy        ; unaligned, do the slow thing...
  798. +    bcc.s    quickmov1        ; both even, ok
  799. +    subq.l    #1,d0            ; both odd, can be fixed
  800. +    move.b    (a1)+,(a0)+
  801. +    bra.s    quickmov1
  802. +
  803.  _quickmove:
  804.      move.l    4(sp),a0        ; get dst
  805.      move.l    8(sp),a1        ; get src
  806.      move.l    12(sp),d0        ; get nbytes
  807. +quickmov1:
  808. +    move.w    #$1ff,d1
  809. +    and.w    d0,d1            ; d1 = nbytes % 512
  810.      lsr.l    #8,d0            ; 
  811.      lsr.l    #1,d0            ; d0 = nbytes / 512
  812.      subq.l    #1,d0            ; prepare for dbra loop
  813. @@ -50,13 +85,34 @@
  814.      movem.l    (sp)+,d1-d7/a2-a6    ; pop registers
  815.  
  816.  Leftover:                ; do the remaining bytes
  817. -    move.l    12(sp),d1
  818. -    and.w    #$01ff,d1        ; d1 = nbytes % 512
  819. +    moveq.l    #3,d0
  820. +    and.w    d1,d0
  821. +    lsr.w    #2,d1
  822.      subq.w    #1,d1            ; prepare for dbra loop
  823. +    bmi.s    L4done
  824. +    lsr.w    #1,d1
  825. +    bcc.s    L23
  826. +L2l:
  827. +    move.l    (a1)+,(a0)+
  828. +L23:
  829. +    move.l    (a1)+,(a0)+
  830. +    dbra    d1,L2l
  831. +L4done:
  832. +    subq.w    #1,d0            ; prepare for dbra loop
  833.      bmi.s    Ldone
  834.  L2:
  835.      move.b    (a1)+,(a0)+
  836. -    dbra    d1,L2
  837. +    dbra    d0,L2
  838.  Ldone:
  839.      rts                ; return
  840. +
  841. +bytecopy:
  842. +    subq.l    #1,d0            ; prepare for dbra loop
  843. +    move.l    d0,d1
  844. +    swap    d1
  845. +L3:
  846. +    move.b    (a1)+,(a0)+
  847. +    dbra    d0,L3
  848. +    dbra    d1,L3
  849. +    rts                ; return
  850.      END
  851. Index: sproto.h
  852. @@ -29,6 +29,7 @@
  853.  
  854.  /* quickmov.s */
  855.  void ARGS_ON_STACK quickmove P_((void *dst, void *src, long nbytes));
  856. +void ARGS_ON_STACK quickmovb P_((void *dst, const void *src, long nbytes));
  857.  
  858.  /* syscall.s */
  859.  char * ARGS_ON_STACK lineA0 P_((void));
  860. Index: tty.c
  861. @@ -87,6 +87,7 @@
  862.      unsigned char ch, *ptr;
  863.      int rdmode, mode;
  864.      struct tty *tty;
  865. +    extern FILESYS bios_filesys;
  866.  
  867.      tty = (struct tty *)f->devinfo;
  868.      assert(tty != 0);
  869. @@ -108,6 +109,21 @@
  870.          rdmode = COOKED|NOECHO;
  871.          mode = T_TOS | T_ECHO;
  872.      }
  873. +#if 1
  874. +    /* see if we can do fast RAW byte IO thru the device driver... */
  875. +    if (rdmode == RAW && !(tty->state & TS_ESC) &&
  876. +        (f->fc.fs != &bios_filesys ||
  877. +        (nbytes > 1 &&
  878. +         ((struct bios_file *)f->fc.index)->drvsize >
  879. +            offsetof (DEVDRV, readb))) &&
  880. +        *f->dev->readb &&
  881. +        ((f->flags & O_HEAD) ||
  882. +        !tty->pgrp || tty->pgrp == curproc->pgrp ||
  883. +        f->fc.dev != curproc->control->fc.dev ||
  884. +        f->fc.index != curproc->control->fc.index) &&
  885. +        (bytes_read = (*f->dev->readb)(f, buf, nbytes)) != EUNDEV)
  886. +        return bytes_read;
  887. +#endif
  888.  
  889.      ptr = buf;
  890.  
  891. @@ -243,6 +259,31 @@
  892.      return bytes_read;
  893.  }
  894.  
  895. +/* job control checks */
  896. +/* AKP: added T_TOSTOP; don't stop BG output if T_TOSTOP is clear */
  897. +/*
  898. +entropy: only do the job control if SIGTTOU is neither blocked nor ignored,
  899. +and only for the controlling tty (IEEE 1003.1-1990 7.1.1.4 79-87).
  900. +BUG:  if the process group is orphaned and SIGTTOU *is not* blocked
  901. +or ignored, we should return EIO instead of signalling.
  902. +*/
  903. +INLINE void
  904. +tty_checkttou (f, tty)
  905. +    FILEPTR *f;
  906. +    struct tty *tty;
  907. +{
  908. +    if (tty->pgrp && tty->pgrp != curproc->pgrp &&
  909. +             (tty->sg.sg_flags & T_TOSTOP) &&
  910. +                 (curproc->sighandle[SIGTTOU] != SIG_IGN) &&
  911. +                 ((curproc->sigmask & (1L << SIGTTOU)) == 0L) &&
  912. +                 (f->fc.dev == curproc->control->fc.dev) &&
  913. +                 (f->fc.index == curproc->control->fc.index)) {
  914. +        TRACE(("job control: tty pgrp is %d proc pgrp is %d",
  915. +            tty->pgrp, curproc->pgrp));
  916. +        killgroup(curproc->pgrp, SIGTTOU);
  917. +    }
  918. +}
  919. +
  920.  long
  921.  tty_write(f, buf, nbytes)
  922.      FILEPTR *f;
  923. @@ -258,6 +299,7 @@
  924.      static long cr_char = '\r';
  925.  #define LBUFSIZ 128
  926.      long lbuf[LBUFSIZ];
  927. +    extern FILESYS bios_filesys;
  928.  
  929.      tty = (struct tty *)f->devinfo;
  930.      assert(tty != 0);
  931. @@ -286,6 +328,20 @@
  932.      else
  933.          mode = 0;
  934.  
  935. +#if 1
  936. +    /* see if we can do fast RAW byte IO thru the device driver... */
  937. +    if (!mode && !use_putchar &&
  938. +        (f->fc.fs != &bios_filesys ||
  939. +        (nbytes > 1 && rwmode == RAW &&
  940. +         ((struct bios_file *)f->fc.index)->drvsize >
  941. +            offsetof (DEVDRV, writeb))) && *f->dev->writeb) {
  942. +
  943. +        tty_checkttou (f, tty);
  944. +        if ((bytes_written = (*f->dev->writeb)(f, buf, nbytes)) != EUNDEV)
  945. +            return bytes_written;
  946. +    }
  947. +#endif
  948. +
  949.  /*
  950.   * we always write at least 1 byte with tty_putchar, since that takes
  951.   * care of job control and terminal states. After that, we may be able
  952. @@ -801,6 +857,9 @@
  953.          }
  954.          goto do_putchar;
  955.      }
  956. +#if 1
  957. +    tty_checkttou (f, tty);
  958. +#else
  959.  /* job control checks */
  960.  /* AKP: added T_TOSTOP; don't stop BG output if T_TOSTOP is clear */
  961.  /*
  962. @@ -819,6 +878,7 @@
  963.              tty->pgrp, curproc->pgrp));
  964.          killgroup(curproc->pgrp, SIGTTOU);
  965.      }
  966. +#endif
  967.  
  968.      if (mode & COOKED) {
  969.          tty->state |= TS_COOKED;
  970. Index: types.h
  971. @@ -16,7 +16,9 @@
  972.  /* structure used to hold i/o buffers */
  973.  typedef struct io_rec {
  974.      char *bufaddr;
  975. -    short buflen, head, tail, low_water, hi_water;
  976. +    short buflen;
  977. +    volatile short head, tail;
  978. +    short low_water, hi_water;
  979.  } IOREC_T;
  980.  
  981.  /* Bconmap struct, * returned by Bconmap(-2) */
  982. Index: xbios.c
  983. @@ -104,6 +104,21 @@
  984.      if (!f) return EIHNDL;
  985.  
  986.      if (is_terminal(f)) {
  987. +#if 1
  988. +        extern FILESYS bios_filesys;
  989. +
  990. +        /* see if we can do fast RAW byte IO thru the device driver... */
  991. +        if ((f->fc.fs != &bios_filesys ||
  992. +            (towrite > 1 &&
  993. +             ((struct bios_file *)f->fc.index)->drvsize >
  994. +                offsetof (DEVDRV, writeb))) && *f->dev->writeb) {
  995. +            struct tty *tty = (struct tty *)f->devinfo;
  996. +
  997. +            tty_checkttou (f, tty);
  998. +            if ((towrite = (*f->dev->writeb)(f, buf, towrite)) != EUNDEV)
  999. +                return towrite;
  1000. +        }
  1001. +#endif
  1002.          while (cnt >= 0) {
  1003.              tty_putchar(f, (long)*buf, RAW);
  1004.              buf++; cnt--;
  1005. @@ -163,7 +178,7 @@
  1006.  {
  1007.      long rsval;
  1008.      static int oldbaud = -1;
  1009. -    int ret_oldbaud = 0;
  1010. +    int b, ret_oldbaud = 0;
  1011.      extern struct tty ttmfp_tty;
  1012.      extern struct bios_tty bttys[];
  1013.      extern short btty_max;
  1014. @@ -230,6 +245,10 @@
  1015.      rsval = Rsconf(baud, flow, uc, rs, ts, sc);
  1016.      if (ret_oldbaud)
  1017.          rsval = (long) oldbaud;
  1018. +    b = 0;
  1019. +    if (baud >= 0 &&
  1020. +        (!has_bconmap || (unsigned)(b = curproc->bconmap-6) < btty_max))
  1021. +        bttys[b].ospeed = bttys[b].ispeed = (unsigned)baud<bttys[b].maxbaud ? bttys[b].baudmap[baud] : -1;
  1022.  
  1023.      return rsval;
  1024.  }
  1025.  
  1026. 3. ptys can also have readb+writeb (for the slave->master pipe), and
  1027. use memcpy too (all pipes).  and really buffer 4K not 4K - 1 byte so the
  1028. copies are aligned more often...
  1029.  
  1030. Index: pipefs.c
  1031. @@ -35,6 +35,10 @@
  1032.  static long    ARGS_ON_STACK pipe_open    P_((FILEPTR *f));
  1033.  static long    ARGS_ON_STACK pipe_write    P_((FILEPTR *f, const char *buf, long bytes));
  1034.  static long    ARGS_ON_STACK pipe_read    P_((FILEPTR *f, char *buf, long bytes));
  1035. +static long    ARGS_ON_STACK pty_write        P_((FILEPTR *f, const char *buf, long bytes));
  1036. +static long    ARGS_ON_STACK pty_read    P_((FILEPTR *f, char *buf, long bytes));
  1037. +static long    ARGS_ON_STACK pty_writeb    P_((FILEPTR *f, const char *buf, long bytes));
  1038. +static long    ARGS_ON_STACK pty_readb    P_((FILEPTR *f, char *buf, long bytes));
  1039.  static long    ARGS_ON_STACK pipe_lseek    P_((FILEPTR *f, long where, int whence));
  1040.  static long    ARGS_ON_STACK pipe_ioctl    P_((FILEPTR *f, int mode, void *buf));
  1041.  static long    ARGS_ON_STACK pipe_datime    P_((FILEPTR *f, short *time, int rwflag));
  1042. @@ -47,8 +51,10 @@
  1043.      pipe_close, pipe_select, pipe_unselect
  1044.  };
  1045.  
  1046. -/* ptys and pipes can share the same driver, for now */
  1047. -#define pty_device pipe_device
  1048. +DEVDRV pty_device = {
  1049. +    pipe_open, pty_write, pty_read, pipe_lseek, pipe_ioctl, pipe_datime,
  1050. +    pipe_close, pipe_select, pipe_unselect, pty_writeb, pty_readb
  1051. +};
  1052.  
  1053.  FILESYS pipe_filesys = {
  1054.      (FILESYS *)0,
  1055. @@ -79,7 +85,7 @@
  1056.      int    head, tail;    /* pipe head, tail (head == tail for empty) */
  1057.      long    rsel;        /* process that did select() for reads */
  1058.      long    wsel;        /* process that did select() for writes */
  1059. -    char    buf[PIPESIZ];    /* pipe data */
  1060. +    char    buf[PIPESIZ+4];    /* pipe data */
  1061.  };
  1062.  
  1063.  struct fifo {
  1064. @@ -610,8 +616,8 @@
  1065.      if (nbytes > 0 && nbytes <= PIPE_BUF) {
  1066.  check_atomicity:
  1067.          r = p->tail - p->head;
  1068. -        if (r < 0) r += PIPESIZ;
  1069. -        r = (PIPESIZ-1) - r; /* r is the number of bytes we can write */
  1070. +        if (r < 0) r += PIPESIZ+4;
  1071. +        r = PIPESIZ - r; /* r is the number of bytes we can write */
  1072.          if (r < nbytes) {
  1073.      /* check for broken pipes */
  1074.              if (p->readers == 0 || p->readers == VIRGIN_PIPE) {
  1075. @@ -635,9 +641,48 @@
  1076.  
  1077.      while (nbytes > 0) {
  1078.          ptail = p->tail; phead = p->head;
  1079. -        j = ptail+1;
  1080. -        if (j >= PIPESIZ) j = 0;
  1081. +        j = ptail+4;
  1082. +        if (j >= PIPESIZ+4) j -= PIPESIZ+4;
  1083.          if (j != phead) {
  1084. +#if 1
  1085. +            int free, wrap;
  1086. +
  1087. +            pbuf = p->buf + ptail;
  1088. +            if ((free = phead - j) < 0)
  1089. +                free += PIPESIZ+4;
  1090. +            if (free == PIPESIZ && ((j = ((long)pbuf & 3)))) {
  1091. +    /* if pipe empty we can align pointers */
  1092. +                if ((ptail += 4-j) >= PIPESIZ+4)
  1093. +                    ptail -= PIPESIZ+4;
  1094. +                p->head = phead = ptail;
  1095. +                pbuf = p->buf + ptail;
  1096. +            }
  1097. +            if (free > nbytes)
  1098. +                free = nbytes;
  1099. +            nbytes -= free;
  1100. +            bytes_written += free;
  1101. +
  1102. +            wrap = PIPESIZ+4 - ptail;
  1103. +            if (free < 5) {
  1104. +                while (free--) {
  1105. +                    *pbuf++ = *buf++;
  1106. +                    if (!--wrap)
  1107. +                        pbuf -= PIPESIZ+4;
  1108. +                }
  1109. +                ptail = pbuf - p->buf;
  1110. +            } else {
  1111. +                if (wrap <= free) {
  1112. +                    memcpy (pbuf, buf, wrap);
  1113. +                    memcpy (p->buf, buf + wrap, free - wrap);
  1114. +                    ptail = free - wrap;
  1115. +                } else {
  1116. +                    memcpy (pbuf, buf, free);
  1117. +                    ptail += free;
  1118. +                }
  1119. +                buf += free;
  1120. +            }
  1121. +#else
  1122. +            j -= 3;
  1123.              pbuf = &p->buf[ptail];
  1124.              do {
  1125.                  *pbuf++ = *buf++;
  1126. @@ -645,8 +690,9 @@
  1127.                  if ( (ptail = j) == 0 )
  1128.                      pbuf = &p->buf[0];
  1129.                  j++;
  1130. -                if (j >= PIPESIZ) j = 0;
  1131. +                if (j >= PIPESIZ+4) j = 0;
  1132.              } while ( (nbytes > 0) && (j != phead) );
  1133. +#endif
  1134.              p->tail = ptail;
  1135.          } else {        /* pipe full */
  1136.              if (p->readers == 0 || p->readers == VIRGIN_PIPE) {
  1137. @@ -706,16 +752,48 @@
  1138.      while (nbytes > 0) {
  1139.          phead = p->head; ptail = p->tail;
  1140.          if (ptail != phead) {
  1141. +#if 1
  1142. +            int left, wrap;
  1143. +
  1144. +            pbuf = p->buf + phead;
  1145. +            if ((left = ptail - phead) < 0)
  1146. +                left += PIPESIZ+4;
  1147. +            if (left > nbytes)
  1148. +                left = nbytes;
  1149. +            nbytes -= left;
  1150. +            bytes_read += left;
  1151. +
  1152. +            wrap = PIPESIZ+4 - phead;
  1153. +            if (left <= 5) {
  1154. +                while (left--) {
  1155. +                    *buf++ = *pbuf++;
  1156. +                    if (!--wrap)
  1157. +                        pbuf -= PIPESIZ+4;
  1158. +                }
  1159. +                phead = pbuf - p->buf;
  1160. +            } else {
  1161. +                if (wrap <= left) {
  1162. +                    memcpy (buf, pbuf, wrap);
  1163. +                    memcpy (buf + wrap, p->buf, left - wrap);
  1164. +                    phead = left - wrap;
  1165. +                } else {
  1166. +                    memcpy (buf, pbuf, left);
  1167. +                    phead += left;
  1168. +                }
  1169. +                buf += left;
  1170. +            }
  1171. +#else
  1172.              pbuf = &p->buf[phead];
  1173.              do {
  1174.                  *buf++ = *pbuf++;
  1175.                  nbytes--; bytes_read++;
  1176.                  phead++;
  1177. -                if (phead >= PIPESIZ) {
  1178. +                if (phead >= PIPESIZ+4) {
  1179.                      phead = 0;
  1180.                      pbuf = &p->buf[phead];
  1181.                  }
  1182.              } while ( (nbytes > 0) && (phead != ptail) );
  1183. +#endif
  1184.              p->head = phead;
  1185.          }
  1186.          else if (p->writers <= 0 || p->writers == VIRGIN_PIPE) {
  1187. @@ -752,6 +830,64 @@
  1188.  }
  1189.  
  1190.  static long ARGS_ON_STACK 
  1191. +pty_write(f, buf, nbytes)
  1192. +    FILEPTR *f; const char *buf; long nbytes;
  1193. +{
  1194. +    long bytes_written = 0;
  1195. +
  1196. +    if (!nbytes)
  1197. +        return 0;
  1198. +    if (f->flags & O_HEAD)
  1199. +        return pipe_write(f, buf, nbytes);
  1200. +    if (nbytes != 4)
  1201. +        ALERT("pty_write: slave nbytes != 4");
  1202. +    bytes_written = pipe_write(f, buf+3, 1);
  1203. +    if (bytes_written == 1)
  1204. +        bytes_written = 4;
  1205. +    return bytes_written;
  1206. +}
  1207. +
  1208. +static long ARGS_ON_STACK 
  1209. +pty_read(f, buf, nbytes)
  1210. +    FILEPTR *f; char *buf; long nbytes;
  1211. +{
  1212. +    long bytes_read = 0;
  1213. +
  1214. +    if (!nbytes)
  1215. +        return 0;
  1216. +    if (!(f->flags & O_HEAD))
  1217. +        return pipe_read(f, buf, nbytes);
  1218. +    if (nbytes != 4)
  1219. +        ALERT("pty_read: master nbytes != 4");
  1220. +    bytes_read = pipe_read(f, buf+3, 1);
  1221. +    if (bytes_read == 1)
  1222. +        bytes_read = 4;
  1223. +    return bytes_read;
  1224. +}
  1225. +
  1226. +static long ARGS_ON_STACK 
  1227. +pty_writeb(f, buf, nbytes)
  1228. +    FILEPTR *f; const char *buf; long nbytes;
  1229. +{
  1230. +    if (!nbytes)
  1231. +        return 0;
  1232. +    if (f->flags & O_HEAD)
  1233. +        return EUNDEV;
  1234. +    return pipe_write(f, buf, nbytes);
  1235. +}
  1236. +
  1237. +static long ARGS_ON_STACK 
  1238. +pty_readb(f, buf, nbytes)
  1239. +    FILEPTR *f; char *buf; long nbytes;
  1240. +{
  1241. +    if (!nbytes)
  1242. +        return 0;
  1243. +    if (!(f->flags & O_HEAD))
  1244. +        return EUNDEV;
  1245. +    return pipe_read(f, buf, nbytes);
  1246. +}
  1247. +
  1248. +static long ARGS_ON_STACK 
  1249.  pipe_ioctl(f, mode, buf)
  1250.      FILEPTR *f; int mode; void *buf;
  1251.  {
  1252. @@ -772,8 +908,8 @@
  1253.                  r = -1;
  1254.              } else {
  1255.                  r = p->tail - p->head;
  1256. -                if (r < 0) r += PIPESIZ;
  1257. -                if (is_terminal(f))
  1258. +                if (r < 0) r += PIPESIZ+4;
  1259. +                if (is_terminal(f) && !(f->flags & O_HEAD))
  1260.                      r = r >> 2;    /* r /= 4 */
  1261.                  if (!r && p->writers <= 0) {
  1262.                      DEBUG(("pipe FIONREAD: no writers"));
  1263. @@ -789,9 +925,9 @@
  1264.                  r = -1;
  1265.              } else {
  1266.                  r = p->tail - p->head;
  1267. -                if (r < 0) r += PIPESIZ;
  1268. -                r = (PIPESIZ-1) - r;
  1269. -                if (is_terminal(f))
  1270. +                if (r < 0) r += PIPESIZ+4;
  1271. +                r = PIPESIZ - r;
  1272. +                if (is_terminal(f) && (f->flags & O_HEAD))
  1273.                      r = r >> 2;    /* r /= 4 */
  1274.              }
  1275.              *((long *) buf) = r;
  1276. @@ -867,8 +1003,8 @@
  1277.                  r = -1;
  1278.              } else {
  1279.                  r = p->tail - p->head;
  1280. -                if (r < 0) r += PIPESIZ;
  1281. -                if (is_terminal(f))
  1282. +                if (r < 0) r += PIPESIZ+4;
  1283. +                if (is_terminal(f) && (f->flags & O_HEAD))
  1284.                      r = r >> 2;    /* r /= 4 */
  1285.              }
  1286.              *((long *) buf) = r;
  1287. @@ -1081,8 +1217,8 @@
  1288.              DEBUG(("write select on wrong end of pipe"));
  1289.              return 0;
  1290.          }
  1291. -        j = p->tail+1;
  1292. -        if (j >= PIPESIZ) j = 0;
  1293. +        j = p->tail+4;
  1294. +        if (j >= PIPESIZ+4) j -= PIPESIZ+4;
  1295.          if (j != p->head || p->readers <= 0)
  1296.              return 1;    /* data may be written */
  1297.          if (p->wsel)
  1298. Index: tty.c
  1299. @@ -330,14 +330,50 @@
  1300.  
  1301.  #if 1
  1302.      /* see if we can do fast RAW byte IO thru the device driver... */
  1303. -    if (!mode && !use_putchar &&
  1304. +    if (!use_putchar &&
  1305.          (f->fc.fs != &bios_filesys ||
  1306. -        (nbytes > 1 && rwmode == RAW &&
  1307. -         ((struct bios_file *)f->fc.index)->drvsize >
  1308. +        (((struct bios_file *)f->fc.index)->drvsize >
  1309.              offsetof (DEVDRV, writeb))) && *f->dev->writeb) {
  1310.  
  1311.          tty_checkttou (f, tty);
  1312. -        if ((bytes_written = (*f->dev->writeb)(f, buf, nbytes)) != EUNDEV)
  1313. +        if (mode) {    /* i.e. T_CRMODE */
  1314. +            if ((*f->dev->writeb)(f, buf, 0L) != EUNDEV) {
  1315. +    /* write in big chunks if possible; lines if CRMODE
  1316. +     * (if we get here flow control is taken care of by the device)
  1317. +     */
  1318. +                long bytes_to_write = 0;
  1319. +                unsigned const char *s = ptr;
  1320. +
  1321. +                while (nbytes-- > 0) {
  1322. +                    if (*ptr++ == '\n') {
  1323. +                        if ((bytes_to_write = ptr-s-1)) {
  1324. +                            c = (*f->dev->writeb)(f, s,
  1325. +                                bytes_to_write);
  1326. +                            bytes_written += c;
  1327. +                            if (c != bytes_to_write) {
  1328. +                                if (c < 0)
  1329. +                                    bytes_written = c;
  1330. +                                return bytes_written;
  1331. +                            }
  1332. +                        }
  1333. +                        s = ptr-1;
  1334. +                        c = (*f->dev->writeb)(f, "\r", 1);
  1335. +                        if (c != 1) {
  1336. +                            if (c < 0)
  1337. +                                bytes_written = c;
  1338. +                            return bytes_written;
  1339. +                        }
  1340. +                    }
  1341. +                }
  1342. +                if ((bytes_to_write = ptr-s)) {
  1343. +                    c = (*f->dev->writeb)(f, s, bytes_to_write);
  1344. +                    bytes_written += c;
  1345. +                    if (c < 0)
  1346. +                        bytes_written = c;
  1347. +                }
  1348. +                return bytes_written;
  1349. +            }
  1350. +        } else if ((bytes_written = (*f->dev->writeb)(f, buf, nbytes)) != EUNDEV)
  1351.              return bytes_written;
  1352.      }
  1353.  #endif
  1354. Index: biosfs.c
  1355. @@ -1331,6 +1331,11 @@
  1356.      int bdev = f->fc.aux;
  1357.      struct bios_file *b = (struct bios_file *)f->fc.index;
  1358.  
  1359. +/* do the slow thing if tty is not in RAW mode until serial lines
  1360. + * handle control chars properly
  1361. + */
  1362. +    if (!(((struct tty *)f->devinfo)->sg.sg_flags & T_RAW))
  1363. +        return EUNDEV;
  1364.      return iwrite (bdev, buf, bytes, (f->flags & O_NDELAY), b);
  1365.  }
  1366.  
  1367. > Kay.
  1368.  good luck
  1369.     Juergen
  1370. -- 
  1371. J"urgen Lock / nox@jelal.north.de / UUCP: ..!uunet!unido!uniol!jelal!nox
  1372.                                 ...ohne Gewehr
  1373. PGP public key fingerprint =  8A 18 58 54 03 7B FC 12  1F 8B 63 C7 19 27 CF DA 
  1374.